package hnapay

import (
    //"fmt"
    "time"
	"strings"
	//"net/url"
	//"crypto/md5"
	"encoding/json"
	//"wxsdk/utils/mapstruct"
	"github.com/astaxie/beego"
)

type Content struct {
	MerOrderId              string   `json:"merOrderId"`          //商户订单号
	DisplayName             string   `json:"displayName"`         //商户显示名称
	GoodsName               string   `json:"goodsName"`           //商品名称
	GoodsCount              int      `json:"goodsCount"`          //商品数量
	GoodsType               string   `json:"goodsType"` //商品类别
	OrderAmount             int      `json:"orderAmount"`         //订单金额
	OrderCurrencyCode       string   `json:"orderCurrencyCode"` //订单币种
	TradeType               string   `json:"tradeType"`         //贸易类型
	PayType                 string   `json:"payType"`           //支付方式
	OrgCode                 string   `json:"orgCode"` //目标机构资金代码
	PayerAccount            string   `json:"payerAccount"`  //付款方账户
	PayCurrencyCode         string   `json:"payCurrencyCode"`         //交易币种
	SettleCurrencyCode      string   `json:"settleCurrencyCode"`      //结算币种
    ShareFlag               string   `json:"shareFlag"`               //分账标识
	SubMerchantOrderDetails string   `json:"subMerchantOrderDetails"` //分账订单信息
	ReturnUrl               string   `json:"returnUrl"`               //回调地址
	NoticeUrl               string   `json:"noticeUrl"`               //通知地址
	PlatformId              string   `json:"platformId"`    //平台ID
	CustomerId              string   `json:"customerId"`    //商户用户号
	CustomerType            string   `json:"customerType"`  //商户用户类型
	CustomerName            string   `json:"customerName"`  //商户用户姓名
	CustomerIdNo            string   `json:"customerIdNo"`  //商户用户证件号
	CustomerTel             string   `json:"customerTel"`   //商户用户手机号
	BankCardNo              string   `json:"bankCardNo"`    //商户用户银行卡号
	BankCardType            string   `json:"bankCardType"`  //商户用户银行卡类型
	ExpireData              string   `json:"expireData"`    //有效期
	Cvn                     string   `json:"cvn"`           //信用卡安全码
	Remark                  string   `json:"remark"`        //备注
	Reserve1                string   `json:"reserve1"`      //保留字段1
	Reserve2                string   `json:"reserve2"`      //保留字段2
}

type MicroAppPayReq struct {
	Header  *MsgHead `json:"head"`
	Content *Content `json:"content"`
	Sign    string   `json:"sign,omitempty"`
}


/*********返回信息****************/
type PayInfo struct {
	AppId     string `json:"appId"`
	TimeStamp string `json:"timeStamp"`
	NonceStr  string `json:"nonceStr"`
	Package   string `json:"package"`
	SignType  string `json:"signType"`
	PaySign   string `json:"paySign"`
}

type RspContent struct {
	ResponseCode string   `json:"responseCode"` //应答码
	ResponseDesc string   `json:"responseDesc"` //应答描述
	MerOrderId   string   `json:"merOrderId"`   //商户订单号
	DealId       string   `json:"dealId"`       //支付系统交易号
	PayType      string   `json:"payType"`      //支付方式
	//PayInfo      *PayInfo `json:"-"`            //支付参数
	PayInfoT     struct {
	   PayInfoStr string  `json:"payInfo"`
	} `json:"payInfo,omitempty"`
	CompleteTime string   `json:"completeTime"` //完成时间
}

type MicroAppPayRsp struct {
	Header  *MsgHead `json:"head"`
	Content *RspContent `json:"content"`
}

//merCode     商户代码
//orderId     订单编号
//displayName 商户显示名字
//goodsName   商品名字
//goodsCount  商品数量
//amount      订单金额
//currency    订单币种
//tradeType   交易类型
//payType     支付方式
//noticeUrl   支付后的通知地址

func MicroAppPay(merCode,uniqueId,orderId,displayName,goodsName string,goodsCount,amount int,currency,tradeType,payType string,shareFlag,noticeUrl,publicKey,openId string)(payInfo *PayInfo, err error){
	var reqParams = new(MicroAppPayReq)
	msgHeader := new(MsgHead)
	msgHeader.SerCode = "101005"
	msgHeader.MerCode = merCode
	msgHeader.OrderId = uniqueId
	msgHeader.MerDate = time.Now().Format("20060102")  //yyyyMMdd
	msgHeader.MerTime = time.Now().Format("150405")    //hhmmss
	msgHeader.VersionNo = "2.0"
	msgHeader.SignType = "2"
	reqParams.Header = msgHeader
	//
	content := new(Content)
	content.MerOrderId = orderId
	content.DisplayName = displayName
	content.GoodsName = goodsName
	content.GoodsCount = goodsCount
	content.OrderAmount = amount
	content.OrderCurrencyCode = currency
	content.TradeType = tradeType
	content.PayType = payType
	content.OrgCode = "WECHATPAY"
	content.PayerAccount = openId
	content.PayCurrencyCode = currency
	content.SettleCurrencyCode = currency
	content.ShareFlag = shareFlag
	content.ReturnUrl = noticeUrl
	content.NoticeUrl = noticeUrl
	reqParams.Content = content
	if b, err := json.Marshal(reqParams); err == nil {
		//beego.Debug("Before Sign Content:", string(b))
		reqParams.Sign = signMd5(string(b), publicKey)	
	}
	var result string
	if b, err := json.Marshal(reqParams); err == nil {
		//beego.Debug("Before Base64 Req msg1:", string(b))
		result = base64Encode(b)
		//result = url.QueryEscape(msg)
	}
	//
	rsp := new(MicroAppPayRsp)
	reqURL := "https://uwebgate.hnapay.com/webgate/unifiedAPI.htm"
	sdk := NewSDK(reqURL, merCode, publicKey)
	_, err = sdk.Request(result, rsp)
	if err != nil {
		beego.Debug("Hnapay MicroAppPay err:", err.Error())
		return
	}
	//beego.Debug("PayInfoT:", rsp.Content.PayInfoT.PayInfoStr)
	payInfo = new(PayInfo)
	if len(rsp.Content.PayInfoT.PayInfoStr) > 0 {
		payInfo = parsePayRsp(rsp.Content.PayInfoT.PayInfoStr)
	}
	return
}

func parsePayRsp(str string) *PayInfo {
	var rspInfo PayInfo
	str = strings.TrimPrefix(str, "{")
	str = strings.TrimSuffix(str, "}")
	valueArr := strings.Split(str, ",")
	for _, v := range valueArr {
	    if ok := strings.Contains(v, "appId"); ok {   
		   pos := strings.Index(v, "=")
	       if pos != -1 {
			  rspInfo.AppId = v[pos+1:]	
		   }
		}	
		if ok := strings.Contains(v, "timeStamp"); ok {   
		   pos := strings.Index(v, "=")
	       if pos != -1 {
			  rspInfo.TimeStamp = v[pos+1:]	
		   }
		}
		if ok := strings.Contains(v, "nonceStr"); ok {   
		   pos := strings.Index(v, "=")
	       if pos != -1 {
			  rspInfo.NonceStr = v[pos+1:]	
		   }	   
		}
		if ok := strings.Contains(v, "package"); ok {   
		   pos := strings.Index(v, "=")
	       if pos != -1 {
			  rspInfo.Package = v[pos+1:]	
		   }	   
		}
		if ok := strings.Contains(v, "signType"); ok {   
		   pos := strings.Index(v, "=")
	       if pos != -1 {
			  rspInfo.SignType = v[pos+1:]	
		   }		   
		}
		if ok := strings.Contains(v, "paySign"); ok {   
		   pos := strings.Index(v, "=")
	       if pos != -1 {
			  rspInfo.PaySign = v[pos+1:]
		   }	   
		}
	}
    return &rspInfo	
}
